package com.fingard.dsp.bank.directbank.czb02;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.net.WebRequest;
import com.fingard.text.StringHelper;
import com.fingard.text.UrlHelper;
import com.fingard.xml.XmlTextWriter;
import com.koalii.svs.SvsSign;

import java.util.Date;

public class CZB02Base extends DirectBase implements ITcpClient {

    protected String getCharset() {
        return getBankConfig().getCharset("GBK");
    }

    protected void writeCommonHeader(XmlTextWriter xmlWriter, ActSetItem actItem, CZB02Header bankHeader) throws Exception {
        if (StringHelper.isNullOrEmpty(bankHeader.transCode)) {
            throw new Exception("transCode未初始化");
        }
        if (StringHelper.isNullOrEmpty(bankHeader.reqSeqNo)) {
            throw new Exception("reqSeqNo未初始化");
        }

        xmlWriter.writeStartElement("request");
        xmlWriter.writeStartElement("head");
        xmlWriter.writeElementString("jym", bankHeader.transCode);//交易码
        xmlWriter.writeElementString("shlsh", bankHeader.reqSeqNo);//商户流水号
        xmlWriter.writeElementString("shbh", actItem.merchantId);//商户编号
        xmlWriter.writeElementString("hth", getBankConfig().getValueAsString("contractNumber"));//合同号
        xmlWriter.writeElementString("jyrq", Format.Date8Format.format(new Date()));//交易日期
        xmlWriter.writeElementString("jysj", Format.Date6Format.format(new Date()));//交易时间
        xmlWriter.writeElementClosed("fhm");//返回码
        xmlWriter.writeElementClosed("fhxx");//返回信息
        xmlWriter.writeElementClosed("xtlsh");//代收系统流水号
        xmlWriter.writeElementString("bz1", "");//备注1
        xmlWriter.writeElementClosed("bz2");//备注2
        xmlWriter.writeEndElement();//备注2
    }

    /**
     * 证书签名方法 采用attach方式进行数据签名
     *
     * @return signedData签名后数据
     */
    public String signData(String oriData, ActSetItem actSetItem) {
        String signedData = null;
        try {
            signedData = null;
            SvsSign svsSign = new SvsSign();
            String ownKeyStorePath = actSetItem.ownKeyStorePath;
            String ownKeyPassword = actSetItem.ownKeyPassword;
            svsSign.initSignCertAndKey(ownKeyStorePath, ownKeyPassword);
            signedData = svsSign.pkcs7SignData(oriData.getBytes(getCharset())); // attach方式数据签名
        } catch (Exception e) {
        	this.WriteBankLogLn(e, "签名过程发生异常：");
        }
        return signedData;
    }

    /**
     * 发送数据到银行
     *
     * @return
     * @throws Exception
     */
    protected String[] sendToBank(String p_reqStr) throws Exception {
        String[] retStr = new String[]{"", ""};

        String requestType = this.getBankConfig().getValueAsString("requestType");
        String tmpCharset = getCharset();

        int readTimeout = getReadTimeout();
        WriteBankLogLn("readTimeout:" + readTimeout / 1000 + "秒");

        if (requestType.toLowerCase().equals("socket")) {
            if (StringHelper.isNullOrEmpty(bankFront.serverIP) && StringHelper.isNullOrEmpty(bankFront.serverPort) && StringHelper.hasAnyChar(bankFront.serverURL)) {
                String[] ipport = UrlHelper.pickupIpAndPort(bankFront.serverURL);
                if (StringHelper.hasAnyChar(ipport[0]) && StringHelper.hasAnyChar(ipport[1])) {
                    bankFront.serverIP = ipport[0];
                    bankFront.serverPort = ipport[1];
                }
            }
            WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP + ":" + bankFront.serverPort + ",requestType:" + requestType);
            if (StringHelper.isNullOrEmpty(bankFront.serverIP) || StringHelper.isNullOrEmpty(bankFront.serverPort)) {
                retStr[0] = FailCode.E9981;
                retStr[1] = "未设置前置机的serverIP或serverPort";
            } else {
                TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(bankFront.serverPort), this);
                tmpClient.timeoutMil = readTimeout;
                byte[] tmpBytesBody = p_reqStr.getBytes(tmpCharset);
                String tmpHead = String.format("%08d", tmpBytesBody.length);

                byte[] tmpBytesHead = tmpHead.getBytes(tmpCharset);

                byte[] tmpBytesSend = new byte[tmpBytesHead.length + tmpBytesBody.length];
                System.arraycopy(tmpBytesHead, 0, tmpBytesSend, 0, tmpBytesHead.length);
                System.arraycopy(tmpBytesBody, 0, tmpBytesSend, tmpBytesHead.length, tmpBytesBody.length);

                WriteBankLogStep2(tmpHead + p_reqStr);
                TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpBytesSend);
                if (StringHelper.isNullOrEmpty(tmpReceiver.connState)) {
                    String tmpBkStr = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, tmpCharset);
                    WriteBankLogStep3(tmpBkStr);
                }
                retStr[0] = tmpReceiver.connState;
                if (tmpReceiver.isCompleted) {
                    retStr[1] = new String(tmpReceiver.recBytes, tmpReceiver.contentStartIndex, tmpReceiver.contentLength, tmpCharset);
                } else {
                    retStr[1] = tmpReceiver.getConnMsg();
                    WriteBankLogLn(retStr[1]);
                }
            }
        } else {
            WriteBankLogLn("2.提交银行的地址：" + bankFront.serverURL + ",requestType:"
                    + requestType);
            WriteBankLogStep2(p_reqStr);

            WebRequest tmpWebRequest = new WebRequest(bankFront.serverURL);
            tmpWebRequest.setLogCode(this.getLogCode());
            tmpWebRequest.setBankFront(this.bankFront);
            tmpWebRequest.setConnectTimeout(10000);

            tmpWebRequest.setReadTimeout(readTimeout);
            tmpWebRequest.setRequestProperty("connection", "Close");

            byte[] tmpUpBytes = p_reqStr.getBytes(tmpCharset);
            String tmpHead = String.format("%08d", tmpUpBytes.length);

            byte[] tmpBytesHead = tmpHead.getBytes(tmpCharset);

            byte[] tmpBytesSend = new byte[tmpBytesHead.length + tmpUpBytes.length];
            System.arraycopy(tmpBytesHead, 0, tmpBytesSend, 0, tmpBytesHead.length);
            System.arraycopy(tmpUpBytes, 0, tmpBytesSend, tmpBytesHead.length, tmpUpBytes.length);

            WriteBankLogStep2(tmpHead + p_reqStr);
            retStr = tmpWebRequest.upload(tmpBytesSend, tmpCharset);
            WriteBankLogStep3(retStr[1]);
            if (retStr[0].length() == 0) {
                int tmpIndex = retStr[1].indexOf("<");
                if (tmpIndex > 0) {
                    retStr[1] = retStr[1].substring(tmpIndex);
                }
            }
        }
        return retStr;
    }

    protected String[] sendToBanks(String p_reqStr) throws Exception {
        String[] retStr = new String[]{"", ""};

        String requestType = this.getBankConfig().getValueAsString("requestType");
        String tmpCharset = getCharset();

        int readTimeout = getReadTimeout()*3;
        WriteBankLogLn("readTimeout:" + readTimeout / 1000 + "秒");

        if (StringHelper.isNullOrEmpty(bankFront.serverIP) && StringHelper.isNullOrEmpty(bankFront.filePort) && StringHelper.hasAnyChar(bankFront.serverURL)) {
            String[] ipport = UrlHelper.pickupIpAndPort(bankFront.serverURL);
            if (StringHelper.hasAnyChar(ipport[0]) && StringHelper.hasAnyChar(ipport[1])) {
                bankFront.serverIP = ipport[0];
                bankFront.filePort = ipport[1];
            }
        }
        WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP + ":" + bankFront.filePort + ",requestType:" + requestType);
        if (StringHelper.isNullOrEmpty(bankFront.serverIP) || StringHelper.isNullOrEmpty(bankFront.filePort)) {
            retStr[0] = FailCode.E9981;
            retStr[1] = "未设置前置机的serverIP或serverPort";
        } else {
            TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(bankFront.filePort), this);
            tmpClient.timeoutMil = readTimeout;
            byte[] tmpBytesBody = p_reqStr.getBytes(tmpCharset);
            String tmpHead = String.format("%08d", tmpBytesBody.length);

            byte[] tmpBytesHead = tmpHead.getBytes(tmpCharset);

            byte[] tmpBytesSend = new byte[tmpBytesHead.length + tmpBytesBody.length];
            System.arraycopy(tmpBytesHead, 0, tmpBytesSend, 0, tmpBytesHead.length);
            System.arraycopy(tmpBytesBody, 0, tmpBytesSend, tmpBytesHead.length, tmpBytesBody.length);

            WriteBankLogStep2(tmpHead + p_reqStr);
            TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpBytesSend);
            retStr[0] = tmpReceiver.connState;
            if (tmpReceiver.recBytes != null) {
                retStr[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, getCharset());
            } else {
                retStr[1] = tmpReceiver.getConnMsg();
            }
            WriteBankLogStep3(retStr[1]);
            if (!tmpReceiver.isCompleted) {
                WriteBankLogLn(tmpReceiver.getConnMsg());
            }
        }
        return retStr;
    }


    @Override
    public void getContentLength(TcpReceiver p_receiver) throws Exception {
        if (p_receiver.contentLength == -1) {
            if (p_receiver.readedLength >= 8) {
                p_receiver.contentLength = Integer.parseInt(new String(p_receiver.recBytes, 0, 8, getCharset()).trim());
                p_receiver.contentStartIndex = 8;
            }
        }
    }
}
